package spring.fox;


import fox.framework.rpc.client.RpcRegister;
import fox.framework.rpc.client.message.RpcClientRequestInterceptor;
import fox.framework.rpc.client.register.ZookeeperRegister;
import fox.framework.rpc.context.RpcApplicationConfigureAdapter;
import fox.framework.rpc.context.RpcApplicationConfigurer;
import fox.framework.rpc.context.processor.RpcApplicationProcessor;
import fox.framework.rpc.converter.RpcMessageConverter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import spring.fox.context.SpringFoxRpcApplicationContext;
import spring.fox.lifecycle.RpcApplicationLifeCycle;

import java.util.List;
import java.util.stream.Collectors;

@EnableConfigurationProperties(SpringFoxConfigureProperties.class)
public class SpringRpcAutoConfiguration implements BeanFactoryAware {

    @Autowired
    private SpringFoxConfigureProperties properties;

    private BeanFactory beanFactory;

    @Bean("springFoxRpcApplicationContext")
    public SpringFoxRpcApplicationContext springFoxRpcApplicationContext(RpcApplicationConfigurer configurer) {
        return new SpringFoxRpcApplicationContext(configurer);
    }

    @Bean
    public RpcApplicationLifeCycle rpcApplicationLifeCycle(){
        return new RpcApplicationLifeCycle();
    }

    @Bean
    public RpcApplicationConfigurer rpcApplicationConfigurer() {
        ObjectProvider<RpcApplicationProcessor> processorProvider = beanFactory.getBeanProvider(RpcApplicationProcessor.class);
        ObjectProvider<RpcMessageConverter> messageConverterProvider = beanFactory.getBeanProvider(RpcMessageConverter.class);
        ObjectProvider<RpcClientRequestInterceptor> requestInterceptorProvider = beanFactory.getBeanProvider(RpcClientRequestInterceptor.class);

        return new RpcApplicationConfigureAdapter() {

            @Override
            public String getApplicationName() {
                return properties.getApplicationName();
            }

            @Override
            public String getBind() {
                return properties.getBind();
            }

            @Override
            public int getPort() {
                return properties.getPort();
            }

            @Override
            public String getGlobalGroup() {
                return properties.getGroup();
            }


            @Override
            public RpcRegister getRegister() {
                switch (properties.getRegister()){
                    case "zookeeper":
                        return new ZookeeperRegister(properties.getServers());
                    default:
                        return super.getRegister();
                }
            }

            @Override
            protected List<RpcMessageConverter> addRpcMessageConverter() {
                return  messageConverterProvider.orderedStream().filter(v -> v != null).collect(Collectors.toList());
            }

            @Override
            protected List<RpcApplicationProcessor> addRpcApplicationProcessor() {
                return processorProvider.orderedStream().filter(v -> v != null).collect(Collectors.toList());
            }

            @Override
            public List<RpcClientRequestInterceptor> getClientRequestInterceptors() {
                return requestInterceptorProvider.orderedStream().filter(v -> v != null).collect(Collectors.toList());
            }
        };
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
}
